using System;
using System.Collections;
using System.IO;
using System.Text;
using Slaks.DocumentSerialization.Document;
using Slaks.Graphs;
using Slaks.Graphs.Category;
using Slaks.Graphs.Comparators;
using Slaks.Graphs.GraphBuilder;
using Slaks.Graphs.GraphBuilder.Slaks;
using Slaks.Graphs.GraphBuilder.TFIDFRelated.Slaks;

namespace Vector2SvmConverter
{
	public class Converter
	{
		private string m_outputFile;
		private string m_parsedFileLabeled;
		private string m_parsedFileUnlabeled;
		private string m_categoryFile;
		private int m_pruning;
		private BuilderType m_representation;
		private string m_termDocumentFrequencyPath;
		public Converter(string outputfile,string parsedfileLabeled,string parsedfileUnlebeled,string categoryfile,int pruning,string termDocumentFrequencyPath,BuilderType representation)
		{
			m_outputFile = outputfile;
			m_parsedFileLabeled = parsedfileLabeled;
			m_parsedFileUnlabeled = parsedfileUnlebeled;
			m_categoryFile = categoryfile;
			m_pruning = pruning;
			m_representation = representation;
			m_termDocumentFrequencyPath = termDocumentFrequencyPath;
		}

		/// <summary>
		/// Convert file and get the records for shuffling for training and testing
		/// </summary>
		/// <returns></returns>
		public IList Convert()
		{
			StreamWriter writer = null;
			IList record = new ArrayList();
			try
			{
			  NormalizedFrequencyRepresentationSlaks normalizedRepresentation = new NormalizedFrequencyRepresentationSlaks();
				StandardTFIDFRepresentationSlaks standardTFIDFrepresentation = new StandardTFIDFRepresentationSlaks();

				Id2DocumentFrequencyMap id2DocumentFrequencyMap = TermDocumentFrequencySerialization.ReadXml(m_termDocumentFrequencyPath);

				IList list = Slaks.DocumentSerialization.ParsedFiles.ParsedFiles.ReadXml(m_parsedFileLabeled);
				Document2CategoryMap doc2CatMap = CategoryReader.ReadCategoryFile(m_categoryFile);

				if (doc2CatMap.Count < list.Count) throw new Exception("There are less categories than the number of files");
				IList categoryList = Slaks.Graphs.Category.CategoryReader.GetCategoryList();

				writer = new StreamWriter(m_outputFile);
				
				Graph graph = null;

				//write labeled
				foreach(string file in list)
				{
					Document doc = Xml2Document.ReadXml(file);
					if (m_representation == BuilderType.NormalizedFrequencyRepresentationSlaks)
						graph = normalizedRepresentation.Build(doc,m_pruning);
					else if (m_representation == BuilderType.StandardTFIDFRepresentationSlaks)
					{
						graph = standardTFIDFrepresentation.Build(doc,m_pruning,id2DocumentFrequencyMap,list.Count);
						graph.GetVertexList().Sort(new FrequencyComparer());
						double mostFrequency = graph.GetVertexList()[0].Frequency;
						//normalize
						foreach(Vertex v in graph.GetVertexList())
						{
							v.Frequency = v.Frequency / mostFrequency;
						}
					}
					else throw new Exception("Convert() labeled: Representation uknown");
					string category = doc2CatMap[graph.Name];
					int categoryIndex = categoryList.IndexOf(category) + 1;
					string recordString = this.WriteVector(writer,categoryIndex,graph,doc);
					record.Add(recordString);
				}

				list = Slaks.DocumentSerialization.ParsedFiles.ParsedFiles.ReadXml(m_parsedFileUnlabeled);
				//write unlabeled
				foreach(string file in list)
				{
					Document doc = Xml2Document.ReadXml(file);
					if (m_representation == BuilderType.NormalizedFrequencyRepresentationSlaks)
						graph = normalizedRepresentation.Build(doc,m_pruning);
					else if (m_representation == BuilderType.StandardTFIDFRepresentationSlaks)
					{
						graph = standardTFIDFrepresentation.Build(doc,m_pruning,id2DocumentFrequencyMap,list.Count);
						graph.GetVertexList().Sort(new FrequencyComparer());
						double mostFrequency = graph.GetVertexList()[0].Frequency;
						//normalize
						foreach(Vertex v in graph.GetVertexList())
						{
							v.Frequency = v.Frequency / mostFrequency;
						}
					}
					else throw new Exception("Convert unlabeled(): Representation uknown");
					
					
					string recordString = this.WriteVector(writer,0,graph,doc);
					record.Add(recordString);
				}
			}
			catch(Exception ex)
			{
				Console.WriteLine(ex.Message + Environment.NewLine + ex.StackTrace);
			}
			finally
			{
				if (writer != null) writer.Close();
			}
			return record;
		}

		private string WriteVector(StreamWriter writer,int categoryIndex, Graph graph, Document document)
		{
			if (graph.GetVertexCount() == 0) return null;
			graph.GetVertexList().Sort();

			StringBuilder builder = new StringBuilder();

			writer.Write(categoryIndex + " ");
			builder.Append(categoryIndex + " ");

			foreach(Vertex vertex in graph.GetVertexList())
			{
				writer.Write(vertex.GetId() + ":" + vertex.Frequency + " ");
				builder.Append(vertex.GetId() + ":" + vertex.Frequency + " ");
			}

			/*
			Vertex ver = graph.GetVertex(document.MostFrequencyInfo.TotalMostFrequentId);
			double frequency = ver.Frequency;
			foreach(Vertex vertex in graph.GetVertexList())
			{
			   writer.Write(vertex.GetId() + ":" + vertex.Frequency / frequency + " ");
				 builder.Append(vertex.GetId() + ":" + vertex.Frequency / frequency + " ");
			}
			*/
			writer.WriteLine("");

			return builder.ToString();
		}

		

	}
}
